package baidu

import (
	"activity_srv/model"
	"context"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
)

const (
	geocodingURL = "https://api.map.baidu.com/geocoding/v3/"            // 地理编码服务
	routePlanURL = "https://api.map.baidu.com/directionlite/v1/driving" // 路线规划服务
)

type Client struct {
	AK string // 百度地图AK密钥
}

func NewClient(ak string) *Client {
	return &Client{AK: ak}
}

// Geocode 地址解析（地理编码）
func (c *Client) Geocode(ctx context.Context, address, region string) (float64, float64, error) {
	params := url.Values{}
	params.Add("ak", c.AK)
	params.Add("address", address)
	if region != "" {
		params.Add("region", region)
	}
	params.Add("output", "json")

	resp, err := http.Get(geocodingURL + "?" + params.Encode())
	if err != nil {
		return 0, 0, fmt.Errorf("地理编码HTTP请求失败: %v", err)
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return 0, 0, fmt.Errorf("读取地理编码响应失败: %v", err)
	}

	var baiduResp struct {
		Status int    `json:"status"`
		Msg    string `json:"message"`
		Result struct {
			Location struct {
				Lat float64 `json:"lat"`
				Lng float64 `json:"lng"`
			} `json:"location"`
			Precise int `json:"precise"`
		} `json:"result"`
	}

	if err := json.Unmarshal(body, &baiduResp); err != nil {
		return 0, 0, fmt.Errorf("解析地理编码响应JSON失败: %v", err)
	}

	if baiduResp.Status != 0 {
		return 0, 0, fmt.Errorf("百度地图地理编码API错误: %s", baiduResp.Msg)
	}

	if baiduResp.Result.Precise != 1 {
		return 0, 0, fmt.Errorf("地址解析不精确，请提供更详细的地址信息")
	}

	return baiduResp.Result.Location.Lat, baiduResp.Result.Location.Lng, nil
}

// GetRoutePlanByAddress 根据地址获取路线规划
func (c *Client) GetRoutePlanByAddress(ctx context.Context, originAddr, destAddr, region string) (*model.RouteResponse, error) {
	// 先进行地理编码，将地址转换为坐标
	originLat, originLng, err := c.Geocode(ctx, originAddr, region)
	if err != nil {
		return nil, fmt.Errorf("起点地址解析失败: %v", err)
	}

	destLat, destLng, err := c.Geocode(ctx, destAddr, region)
	if err != nil {
		return nil, fmt.Errorf("终点地址解析失败: %v", err)
	}

	// 构建请求参数
	params := url.Values{}
	params.Add("ak", c.AK)
	params.Add("origin", fmt.Sprintf("%f,%f", originLat, originLng))
	params.Add("destination", fmt.Sprintf("%f,%f", destLat, destLng))
	params.Add("coord_type", "bd09ll") // 注意：这里应该是"bd09ll"，不是"bd0911"
	params.Add("tactics", "0")

	// 发送HTTP请求
	resp, err := http.Get(routePlanURL + "?" + params.Encode())
	if err != nil {
		return nil, fmt.Errorf("路线规划HTTP请求失败: %v", err)
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("读取路线规划响应失败: %v", err)
	}

	// 解析百度API响应
	var baiduResp struct {
		Status int    `json:"status"`
		Msg    string `json:"message"`
		Result struct {
			Routes []struct {
				Distance int `json:"distance"`
				Duration int `json:"duration"`
				Steps    []struct {
					Distance    int    `json:"distance"`
					Duration    int    `json:"duration"`
					Instruction string `json:"instruction"`
					Path        string `json:"path"`
				} `json:"steps"`
			} `json:"routes"`
		} `json:"result"`
	}

	if err := json.Unmarshal(body, &baiduResp); err != nil {
		return nil, fmt.Errorf("解析路线规划响应JSON失败: %v", err)
	}

	// 检查百度API返回状态
	if baiduResp.Status != 0 {
		return nil, fmt.Errorf("百度地图API错误: %s", baiduResp.Msg)
	}

	// 转换响应格式
	if len(baiduResp.Result.Routes) == 0 {
		return nil, fmt.Errorf("未找到路线")
	}

	route := baiduResp.Result.Routes[0]
	response := &model.RouteResponse{
		Distance:            route.Distance,
		Duration:            route.Duration,
		Message:             "成功",
		OriginLocation:      fmt.Sprintf("%f,%f", originLat, originLng),
		DestinationLocation: fmt.Sprintf("%f,%f", destLat, destLng),
	}

	// 转换每一步路线
	for _, step := range route.Steps {
		// 清理指令中的HTML标签
		instruction := strings.ReplaceAll(step.Instruction, "<b>", "")
		instruction = strings.ReplaceAll(instruction, "</b>", "")
		instruction = strings.ReplaceAll(instruction, "<div>", " ")
		instruction = strings.ReplaceAll(instruction, "</div>", "")
		instruction = strings.ReplaceAll(instruction, "<br>", " ")

		response.Steps = append(response.Steps, &model.RouteStep{
			Distance:    step.Distance,
			Duration:    step.Duration,
			Instruction: instruction,
			Path:        step.Path,
		})
	}

	return response, nil
}
